using System;
using System.Collections.Generic;
using System.IO;

namespace DemoContentLoader
{
    public class ShaderCache
    {
        private Dictionary<SourceShader, byte[]> shaders;
        public ShaderCache(Dictionary<SourceShader, byte[]> shaders)
        {
            this.shaders = shaders;
        }

        public byte[] GetShader(string resourceName)
        {
            return GetShader(new SourceShader { Name = resourceName });
        }
        public byte[] GetShader(string resourceName, params string[] defines)
        {
            return GetShader(new SourceShader { Name = resourceName, Defines = defines });
        }


        public byte[] GetShader(SourceShader sourceShader)
        {
            if (shaders.TryGetValue(sourceShader, out var shader))
            {
                return shader;
            }
            throw new Exception("Shader " + sourceShader + " was not in the shader cache.");
        }

        // *此类都不是线程安全类*

        // 着色器内容存档的格式：
        // 存储在int32中的元素计数
        // {名称-字节码对列表}
        //
        // 其中,每对表示为：
        // 唯一的着色器名称
        // 元素大小(以字节为单位)(Int64)
        // {元素定义的字节块}
        //
        // 其中,每个唯一的元素名称由UTF-16字符串表示,存储为：
        // 字符数(Int32)
        // {字符}


        public static void Save(Dictionary<SourceShader, byte[]> archive, Stream stream)
        {
            // 保存图元数。
            using (var writer = new BinaryWriter(stream))
            {
                writer.Write(archive.Count);

                // 按顺序保存每个元素。
                foreach (var pathShaderPair in archive)
                {
                    SourceShader.Write(writer, pathShaderPair.Key);

                    // 写下元素的大小。
                    var size = pathShaderPair.Value.Length;
                    writer.Write(size);

                    // 写入元素的数据。
                    writer.Write(pathShaderPair.Value, 0, size);
                }
            }
        }

        public static ShaderCache Load(Stream stream)
        {
            var archive = new Dictionary<SourceShader, byte[]>();
            using (var reader = new BinaryReader(stream))
            {
                var count = reader.ReadInt32();

                for (int i = 0; i < count; ++i)
                {
                    // 阅读名称长度。
                    var shader = SourceShader.Read(reader);

                    // 读取内容元素数据本身的大小(以字节为单位)。
                    int sizeInBytes = reader.ReadInt32();
                    var data = new byte[sizeInBytes];
                    reader.Read(data, 0, sizeInBytes);
                    archive.Add(shader, data);

                }
            }
            return new ShaderCache(archive);
        }

    }
}
